import {plot, addColorScale} from 'plotty'
import {decode} from './jpeg_decoder'
import {getInfo} from './getinfo'
import {guid2} from './uuid'
import proj4 from 'proj4'
import mapboxgl from 'mapbox-gl'

function FillLayer (options) {
  this.map = options.map// 必填
  this.breaks = options.breaks
  this.colors = options.colors

  this.contourService
  this.imgCanvas = document.createElement('canvas')
  // 随机生成一个id，当前填色图中source，layer都以这个id为后缀
  let id = guid2()

  this.greyDatas = []
  this.contour_lines
  this.imageInfo
  this.shuzhiMoveEvt

  // 图像source
  this.imageSourceID = 'imageSource' + id
  this.valueSourceID = 'valueSource' + id
  this.contourSourceID = 'contourSource' + id

  this.imageLayerID = 'imageLayer' + id
  this.valueLayerID = 'valueLayer' + id
  this.contourLayerID = 'contourLayer' + id
  this.contourLabelLayerID = 'contourLabelLayer' + id

  // 图层显隐状态
  this.valueLayerShow = false
  this.contourLayerShow = false

  // 初始化source对象
  let canvasSource = {
    type: 'canvas',
    canvas: this.imgCanvas,
    animate: true,
    'coordinates': [
      [-180, 85.1],
      [180, 85.1],
      [180, -85.1],
      [-180, -85.1]
    ]
  }
  this.map.addSource(this.imageSourceID, canvasSource)
  this.map.addSource(this.valueSourceID, {
    'type': 'geojson',
    'data': {
      'type': 'FeatureCollection',
      'features': []
    }
  })

  // 初始化layer对象
  this.map.addLayer({
    'id': this.imageLayerID,
    'source': this.imageSourceID,
    'type': 'raster',
    'paint': {
      'raster-opacity': 0.8
    }
  }, 'admin-1-boundary-bg')
  this.map.addLayer({
    'id': this.valueLayerID,
    'type': 'symbol',
    'source': this.valueSourceID,
    'layout': {
      'text-field': ['get', 'value'],
      'text-font': ['Open Sans Regular'],
      'text-offset': [0, 0]
    },
    paint: {
      'text-color': 'hsl(0, 0%, 78%)',
      'text-halo-color': 'hsla(0, 0%, 13%, 0.75)',
      'text-halo-width': 1,
      'text-halo-blur': 1
    }
  })
  this.contourColors = ['step', ['get', 'level']]
  for (let i = 0; i < this.breaks.length; i++) {
    this.contourColors.push(this.colors[i])
    this.contourColors.push(this.breaks[i])
  }
  this.contourColors.push(['rgb', 255, 255, 255])

  // 默认设置隐藏
  this.map.setLayoutProperty(this.valueLayerID, 'visibility', 'none')

  var _self = this
  this.clickevt = function (e) {
    let value = _self.getRealValueByLngLat([e.lngLat.lng, e.lngLat.lat])
    if (value) {
      new mapboxgl.Popup()
        .setLngLat(e.lngLat)
        .setHTML(value)
        .addTo(_self.map)
    }
  }
}

// 更新等值线，传入等值线的矢量切片服务地址
FillLayer.prototype.updateContour = function (contourService) {
  // 未添加到地图
  let contourSource = this.map.getSource(this.contourSourceID)
  if (!contourService) {
    console.error('未设置等值线数据源！')
    return
  }
  if (contourSource) {
    this.map.removeLayer(this.contourLayerID)
    this.map.removeLayer(this.contourLabelLayerID)
    this.map.removeSource(this.contourSourceID)
  }
  this.map.addSource(this.contourSourceID, {
    'type': 'vector',
    'tiles': [
      contourService
    ],
    'minzoom': 1,
    'maxzoom': 8
  })
  this.map.addLayer({
    'id': this.contourLayerID,
    'type': 'line',
    'source': this.contourSourceID,
    'source-layer': 'contour_line',
    'layout': {
      'line-cap': 'round',
      'line-join': 'round'
    },
    'paint': {
      'line-color': this.contourColors,
      'line-width': 2
    }
  })
  this.map.addLayer({
    'id': this.contourLabelLayerID,
    'type': 'symbol',
    'source': this.contourSourceID,
    'source-layer': 'contour_line',
    'layout': {
      'text-field': ['get', 'level'],
      'text-max-angle': 30,
      'text-font': [
        'DIN Offc Pro Regular'
      ],
      'symbol-placement': 'line',
      'text-padding': 1,
      'text-rotation-alignment': 'map',
      'text-pitch-alignment': 'viewport',
      'text-letter-spacing': 0.01
    },
    'paint': {
      'text-color': 'hsl(0, 0%, 78%)',
      'text-halo-color': 'hsla(0, 0%, 13%, 0.75)',
      'text-halo-width': 1,
      'text-halo-blur': 1
    }
  })
}

// 更新填色图
FillLayer.prototype.updateImg = async function (jsonURL) {
  let _self = this
  // 重置等值线数据源
  this.contourService = jsonURL.replace('.json', '/{z}/{x}/{y}.pbf')

  let info = await getInfo(jsonURL, 'json')
  let jpegurl = jsonURL.replace('.json', '.jpeg')
  let _arraybuffer = await getInfo(jpegurl, 'arraybuffer')
  _self.imageRender(info, _arraybuffer)

  // 同步更新数值图层与等值线图层
  if (this.valueLayerShow) { this.showShuZhiLayer() } else { this.closeShuZhiLayer() }
  if (this.contourLayerShow) { this.showContour() } else { this.closeContour() }
}

FillLayer.prototype.ImageAnimate = async function (jsonURLs, interval) {
  let _self = this
  var currentImage = 0

  let images = await this._loadImages(jsonURLs)
  var frameCount = images.length

  var intervalId = setInterval(function () {
    currentImage = (currentImage + 1) % frameCount
    if (currentImage >= images.length - 1) {
      clearInterval(intervalId)
      return
    }
    let _url = images[currentImage]
    let _source = _self.map.getSource(_self.imageSourceID)
    _source.updateImage({ url: _url })
  }, interval)
}

// 初始化加载图像
FillLayer.prototype._loadImages = async function (jsonURLs) {
  let images = []
  for (let i = 0; i < jsonURLs.length; i++) {
    let jsonURL = jsonURLs[i]
    let info = await getInfo(jsonURL, 'json')
    let jpegurl = jsonURL.replace('.json', '.jpeg')
    let _arraybuffer = await getInfo(jpegurl, 'arraybuffer')
    let _getDataURIByArraybuffer = this._getDataURIByArraybuffer(info, _arraybuffer)
    images.push(_getDataURIByArraybuffer)
  }
  return images
}
FillLayer.prototype._getDataURIByArraybuffer = function (info, arraybuffer) {
  // 提前渲染好
  this.imageRender(info, arraybuffer)
  var strDataURI = this.imgCanvas.toDataURL('image/png')
  return strDataURI
}
// 更新图像根据arraybuffer
FillLayer.prototype.imageRender = function (info, arraybuffer) {
  this.imgCanvas.width = info.width
  this.imgCanvas.height = info.height
  this.imageInfo = info
  // 解析jpeg
  let imageReader = decode(arraybuffer)
  this.greyDatas = []
  for (let y = 0; y < imageReader.height; y++) {
    for (let x = 0; x < imageReader.width; x++) {
      // 通过像素反算真实值
      let k = (y * imageReader.width + x) * 4
      this.greyDatas.push(imageReader.data[k])
    }
  }
  // breaks转灰度值
  let breaks = this.breaks.map(item => {
    return Math.floor(255 * (item - info.min_value) / (info.max_value - info.min_value))
  })
  // breaks归一化
  let _min = breaks[0], _max = breaks[breaks.length - 1]
  let _sum = _max - _min
  let steps = breaks.map(item => {
    let _step = (item - _min) * 1.0 / _sum
    return _step
  })
  // 设置颜色渐变
  addColorScale('mycolorscale', this.colors, steps)
  let imageFillPlot = new plot({
    canvas: this.imgCanvas,
    data: this.greyDatas,
    width: imageReader.width,
    height: imageReader.height,
    domain: [_min, _max],
    colorScale: 'mycolorscale'
  })
  // 渲染
  imageFillPlot.render()
}

// 显示数值信息
// 根据设置的采样间隔
FillLayer.prototype.showShuZhiLayer = function () {
  var _self = this
  let datas = _self.createGridByPixel()
  this.map.getSource(this.valueSourceID).setData(datas)
  this.map.setLayoutProperty(this.valueLayerID, 'visibility', 'visible')
  if (!this.shuzhiMoveEvt) {
    this.shuzhiMoveEvt = function (e) {
      let datas = _self.createGridByPixel()
      _self.map.getSource(_self.valueSourceID).setData(datas)
    }
  }
  // 地图窗口变动事件
  this.map.on('moveend', this.shuzhiMoveEvt)
  this.valueLayerShow = true
}
// 关闭数值信息
FillLayer.prototype.closeShuZhiLayer = function () {
  this.map.setLayoutProperty(this.valueLayerID, 'visibility', 'none')
  if (this.shuzhiMoveEvt) {
    this.map.off('moveend', this.shuzhiMoveEvt)
  }
  this.valueLayerShow = false
}

// 显示等值线
FillLayer.prototype.showContour = function (contourService) {
  if (!contourService) { contourService = this.contourService }
  this.updateContour(contourService)
  this.map.setLayoutProperty(this.contourLayerID, 'visibility', 'visible')
  this.map.setLayoutProperty(this.contourLabelLayerID, 'visibility', 'visible')
  this.contourLayerShow = true
}

// 关闭等值线
FillLayer.prototype.closeContour = function () {
  if (this.map.getLayer(this.contourLayerID) && this.map.getLayer(this.contourLabelLayerID)) {
    this.map.setLayoutProperty(this.contourLayerID, 'visibility', 'none')
    this.map.setLayoutProperty(this.contourLabelLayerID, 'visibility', 'none')
  }
  this.contourLayerShow = false
}

FillLayer.prototype.getRealValueByLngLat = function (lonlat) {
  if (!this.imageInfo) { return null }
  let coors = proj4('EPSG:4326', 'EPSG:3857', [lonlat[0], lonlat[1]])
  // 墨卡托转图像像素
  let x = Math.ceil((coors[0] - (-20026376.39)) / (20026376.39 * 2) * this.imageInfo.width)
  let y = Math.ceil((20048966.10 - coors[1]) / (20048966.10 * 2) * this.imageInfo.height)
  let value = this.greyDatas[y * this.imageInfo.width + x]
  value = value * (this.imageInfo.max_value - this.imageInfo.min_value) / 255 + this.imageInfo.min_value

  if (value) { value = value.toFixed(1) }
  return value
}

// 销毁内置图层对象
FillLayer.prototype.destroy = function () {
  // 取消事件
  this.map.off('click', this.clickevt)
  this.map.off('moveend', this.shuzhiMoveEvt)
  // 删除图层
  this.map.removeLayer(this.imageLayerID)
  this.map.removeLayer(this.valueLayerID)
  this.map.removeLayer(this.contourLayerID)
  this.map.removeLayer(this.contourLabelLayerID)
}

FillLayer.prototype.createGridByPixel = function () {
  var _self = this
  let mapdiv = this.map.getContainer()
  var w = mapdiv.clientWidth || mapdiv.offsetWidth
  var h = mapdiv.clientHeight || mapdiv.offsetHeight
  let datas = {
    'type': 'FeatureCollection',
    'features': []
  }

  for (let i = -50; i < h + 50; i = i + 50) {
    for (let j = -50; j < w + 50; j = j + 50) {
      var coordinate = _self.map.unproject({x: j, y: i})
      datas.features.push({
        'type': 'Feature',
        'properties': {
          value: _self.getRealValueByLngLat([coordinate.lng, coordinate.lat])
        },
        'geometry': {
          'type': 'Point',
          'coordinates': [coordinate.lng, coordinate.lat]
        }
      })
    }
  }
  return datas
}

export {FillLayer}
